const timeRegExp = /\[(\d{2,}):(\d{2})(?:\.(\d{2,3}))?]/

const STATE_PAUSE = 0
const STATE_PLAYING = 1

class Lyric {
  constructor(lyric, handle) {
    this.lyric = lyric
    this.handle = handle
    this.lines = []
    this.timer = null
    this.curNum = 0
    this.state = STATE_PAUSE
    this.pauseStamp = 0
    this.startStamp = 0
    this.init()
  }
  init() {
    let lines = this.lyric.split('\n')
    lines.forEach(line => {
      let res = timeRegExp.exec(line)
      let txt = line.replace(timeRegExp, '').trim()
      if (res && txt) {
        this.lines.push({
          txt,
          time: res[1] * 60 * 1000 + res[2] * 1000 + (res[3] || 0) * 1
        })
      }
    })
    this.lines.sort((a, b) => a.time - b.time )
  }
  callHandle() {
    if (!this.lines[this.curNum]) return
    this.handle({
      lineNum: this.curNum,
      txt: this.lines[this.curNum].txt
    })
  }
  resetPlay() {
    if (this.curNum > this.lines.length) {
      clearTimeout(this.timer)
      return
    }
    let line = this.lines[this.curNum]
    let delay = line.time - (+new Date() - this.startStamp)
    this.timer = setTimeout(() => {
      this.callHandle()
      this.curNum++
      if (this.curNum < this.lines.length && this.state === STATE_PLAYING) {
        this.resetPlay()
      }
    }, delay)
  }
  findCurNum(time) {
    for (let index = 0; index < this.lines.length; index++) {
      if (time <= this.lines[index].time) {
        return index
      }
    }
    return this.lines.length - 1
  }
  togglePlay() {
    let now = +new Date()
    if (this.state === STATE_PLAYING) {
      this.stop()
      this.pauseStamp = now
    } else {
      this.state = STATE_PLAYING
      this.play((this.pauseStamp || now) - (this.startStamp || now))
      this.pauseStamp = 0
    }
  }
  play(startTime = 0, immediately = false) {
    this.curNum = this.findCurNum(startTime)
    if (immediately) {
      this.callHandle()
    }
    this.startStamp = +new Date() - startTime
    this.state = STATE_PLAYING
    this.resetPlay()
  }
  stop() {
    this.state = STATE_PAUSE
    clearTimeout(this.timer)
  }
  seek(offset) {
    this.play(offset, true)
  }
}

export default Lyric
